package com.xiyuan.smartutils.template.engine.expression.operator.arithmetic;

import com.xiyuan.smartutils.StrUtils;
import com.xiyuan.smartutils.Validates;
import com.xiyuan.smartutils.template.engine.exception.ExpressionException;
import com.xiyuan.smartutils.template.engine.expression.operator.Operator;

import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * the description for class _NumOprator
 *
 * @author xiyuan-lgz 2024-02-01 @version v1.0.0 新建与整理
 */
public abstract class _NumOprator extends Operator {
    public static final BigInteger MAX_INT = BigInteger.valueOf(Integer.MAX_VALUE);
    public static final BigInteger MIN_INT = BigInteger.valueOf(Integer.MIN_VALUE);
    
    public static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
    public static final BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE);
    
    public static final BigDecimal MAX_DOUBLE = BigDecimal.valueOf(Double.MAX_VALUE);
    public static final BigDecimal MIN_DOUBLE = BigDecimal.valueOf(Double.MIN_VALUE);
    
    public _NumOprator(String path, int line, int column) {
        super(path, line, column);
    }
    
    protected void checkValue(Object prev, Object next, String msg1, String msg2, String msg3) {
        boolean isNumP = prev != null && (prev instanceof Number || Validates.isFloat(prev.toString()));
        boolean isNumN = prev != null && (next instanceof Number || Validates.isFloat(next.toString()));
        if (!isNumP || !isNumN) {
            // 不是整数和小数
            throw new ExpressionException(this, StrUtils.format("表达式{%s}，格式不正确，%s或%s不是数值型",
                                                                this,
                                                                msg2,
                                                                msg3));
        }
    }
    
    
    public BigInteger parseInteger(Object value) {
        if (value instanceof BigInteger) {return (BigInteger) value;}
        else {return new BigInteger(value.toString());}
    }
    
    public BigDecimal parseDecimal(Object value) {
        if (value instanceof BigDecimal) {return (BigDecimal) value;}
        else {return new BigDecimal(value.toString());}
    }
    
    /**
     * 返回 int/long/BigInteger
     */
    protected Number returnInteger(BigInteger val) {
        if (val.compareTo(MIN_INT) >= 0 && val.compareTo(MAX_INT) <= 0) {
            return val.intValue();
        }
        
        if (val.compareTo(MIN_LONG) >= 0 && val.compareTo(MAX_LONG) <= 0) {
            return val.longValue();
        }
        
        return val;
    }
    
    /**
     * double/BigDecimal
     */
    protected Number returnDecimal(BigDecimal val) {
        if (val.compareTo(MIN_DOUBLE) >= 0 && val.compareTo(MAX_DOUBLE) <= 0) {
            return val.doubleValue();
        }
        return val;
    }
}
